在操作 Collection 時,很常需要把 Collection 裡的元素逐一取出,比方說把 List 裡的元素一個一個印出。寫過其他程式語言的朋友或許會很直覺的想到用 for
或 foreach
等迴圈來操作。不過,在 Kotlin 裡並沒有 foreach
這種寫法,而是可以用 for
做出各種型式的迴圈操作。
val numbers = listOf(1, 3, 5, 7, 9)
// 類似 foreach 的操作,從 numbers 拿出一個個 number
for (number in numbers) {
println(number)
}
// 用 `indices` 取出所有 index,再用 index 取出 Collection 裡的值
for (index in numbers.indices) {
println(numbers[index])
}
// 用 `withIndex()` 同時取出 index 及 value
for ((index, value) in numbers.withIndex()) {
println("$index: $value")
}
雖然 for
迴圈是 Kotlin 原生就有的語法,操作起來也很直覺,不過 Collection 其實本身就支援迴圈操作,直接呼叫 Collection 身上的 method 會更直覺好用喔!在這個章節裡,我們就來看看 forEach()
及 forEachIndexed()
兩個 method 可以怎麼操作?
Collection 本身有一個 forEach()
,就可以完成與 for 一樣的行為。以上面的例子來改寫,就會像:
val numbers = listOf(1, 3, 5, 7, 9)
numbers.forEach {
println(it)
}
從 Collection 身上直接操作,在解讀上可以更符合語義。若是覺得 Kotlin 預設把 Lambda 的對象命名為 it
在這邊不好理解的話,也可以重新命名。
val numbers = listOf(1, 3, 5, 7, 9)
numbers.forEach { number ->
println(number)
}
同樣的語法也適用於 Map,不過要注意 it 就會是一個 Map Entry,取出時要分 key 和 value。
val numberMap = mapOf(1 to "one", 2 to "two", 3 to "three")
numberMap.forEach{
println("key=${it.key}, value=${it.value}")
}
假如是需要用 withIndex()
同時取出索引及元素的話,Collection 也有 forEachIndexed
這個 method 可以用,用法也很直覺,直接在 Lambda 取出即可:
val numbers = listOf(1, 3, 5, 7, 9)
numbers.forEachIndexed { index, element ->
println("index=$index, element=$element")
}
要注意的是,Map 本身就是 key 與 value 的組合,所以沒有 forEachIndexed()
這個 method 的!直接用 forEach()
即可,不過寫法要注意多個 ()
:
val numberMap = mapOf(1 to "one", 2 to "two", 3 to "three")
numberMap.forEach { (key, value) ->
println("key=$key, value=$value")
}
在這個章節裡,我們討論了 Kotlin 裡幾個常用的迴圈寫法。就結果來說沒有差異,就看撰寫者覺得哪個寫法比較符合語義及情境了。為了一覽這些 API 在不同 Collection 上的行為,以下用表格來整理本章所討論到的 method:
行為 | Array | List | Set | Map | |
---|---|---|---|---|---|
forEach{} | 逐一取出元素 | v | v | v | v |
forEachIndexed{} | 逐一取出索引及元素 | v | v | v | x |